﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;

namespace SharpSoft.WPF.Controls.Primitives
{
    /// <summary>
    /// 带有两个滑块的跟踪条
    /// </summary>
    [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
    public class Track2 : FrameworkElement
    {
        public Track2()
        {

        }
        #region 属性

        private Thumb _thumb1;

        public Thumb LowerThumb
        {
            get { return _thumb1; }
            set
            {

                UpdateComponent(_thumb1, value);
                _thumb1 = value;
            }
        }


        private Thumb _thumb2;

        public Thumb HigherThumb
        {
            get { return _thumb2; }
            set
            {
                UpdateComponent(_thumb2, value);
                _thumb2 = value;
            }
        }


        /// <summary>
        /// 滑块的长度
        /// </summary>
        public double ThumbLength
        {
            get { return (double)GetValue(ThumbLengthProperty); }
            set { SetValue(ThumbLengthProperty, value); }
        }

        public static readonly DependencyProperty ThumbLengthProperty =
            DependencyProperty.Register("ThumbLength", typeof(double), typeof(Track2), new PropertyMetadata(10d));




        private RepeatButton _decreaseButton;
        /// <summary>
        /// 递减按钮
        /// </summary>
        public RepeatButton DecreaseRepeatButton
        {
            get { return _decreaseButton; }
            set
            {
                UpdateComponent(_decreaseButton, value);
                _decreaseButton = value;
            }
        }

        private RepeatButton _increaseButton;
        /// <summary>
        /// 递增按钮
        /// </summary>
        public RepeatButton IncreaseRepeatButton
        {
            get { return _increaseButton; }
            set
            {
                UpdateComponent(_increaseButton, value);
                _increaseButton = value;
            }
        }
        /// <summary>
        /// 最小值
        /// </summary>
        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }
        public static readonly DependencyProperty MinimumProperty =
                RangeBase.MinimumProperty.AddOwner(typeof(Track2),
                        new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsArrange));


        /// <summary>
        /// 最大值
        /// </summary>
        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }
        public static readonly DependencyProperty MaximumProperty =
                RangeBase.MaximumProperty.AddOwner(typeof(Track2),
                        new FrameworkPropertyMetadata(1d, FrameworkPropertyMetadataOptions.AffectsArrange));

        /// <summary>
        /// 底值
        /// </summary>
        public double LowerValue
        {
            get { return (double)GetValue(LowerValueProperty); }
            set { SetValue(LowerValueProperty, value); }
        }

        public static readonly DependencyProperty LowerValueProperty =
             RangeSlider.LowerValueProperty.AddOwner(typeof(Track2),
                        new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsArrange));


        /// <summary>
        /// 高值
        /// </summary>
        public double HigherValue
        {
            get { return (double)GetValue(HigherValueProperty); }
            set { SetValue(HigherValueProperty, value); }
        }

        public static readonly DependencyProperty HigherValueProperty =
            RangeSlider.HigherValueProperty.AddOwner(typeof(Track2),
                        new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsArrange));



        /// <summary>
        /// 方向（水平/垂直）
        /// </summary>
        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        public static readonly DependencyProperty OrientationProperty =
            RangeSlider.OrientationProperty.AddOwner(typeof(Track2),
                        new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsArrange));


        #endregion

        #region 控件

        private Visual[] _visualChildren;

        /// <summary>
        /// 更新内部组件
        /// </summary>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        private void UpdateComponent(Control oldValue, Control newValue)
        {
            if (oldValue != newValue)
            {
                if (_visualChildren == null)
                {
                    _visualChildren = new Visual[4];
                }

                if (oldValue != null)
                {
                    // notify the visual layer that the old component has been removed.
                    RemoveVisualChild(oldValue);
                }

                // Remove the old value from our z index list and add new value to end
                int i = 0;
                while (i < 4)
                {
                    // Array isn't full, break
                    if (_visualChildren[i] == null)
                        break;

                    // found the old value
                    if (_visualChildren[i] == oldValue)
                    {
                        // Move values down until end of array or a null element
                        while (i < 3 && _visualChildren[i + 1] != null)
                        {
                            _visualChildren[i] = _visualChildren[i + 1];
                            i++;
                        }
                    }
                    else
                    {
                        i++;
                    }
                }
                // Add newValue at end of z-order
                _visualChildren[i] = newValue;

                AddVisualChild(newValue);

                InvalidateMeasure();
                InvalidateArrange();
            }
        }


        protected override Visual GetVisualChild(int index)
        {
            if (_visualChildren == null)
            {
                throw new Exception("子元素为空。");
            }
            return _visualChildren[index];
        }
        protected override int VisualChildrenCount
        {
            get
            {
                if (_visualChildren == null || _visualChildren[0] == null)
                {
                    return 0;
                }
                else if (_visualChildren[1] == null)
                {
                    return 1;
                }
                else if (_visualChildren[2] == null)
                {
                    return 2;
                }
                else
                {
                    return _visualChildren[3] == null ? 3 : 4;
                }
            }
        }
        /// <summary>
        /// 限制组件的长度不小于0 且不大于总长度
        /// </summary>
        /// <param name="componentLength"></param>
        /// <param name="trackLength"></param>
        private static void CoerceLength(ref double componentLength, double trackLength)
        {
            if (trackLength < 0)
            {
                trackLength = 0;
            }
            if (componentLength < 0)
            {
                componentLength = 0.0;
            }
            else if (componentLength > trackLength || double.IsNaN(componentLength))
            {
                componentLength = trackLength;
            }
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            if (double.IsInfinity(availableSize.Height))
            {
                availableSize.Height = SystemParameters.HorizontalScrollBarHeight;
            }
            if (double.IsInfinity(availableSize.Width))
            {
                availableSize.Width = SystemParameters.VerticalScrollBarWidth;
            }

            if (Orientation == Orientation.Horizontal)
            {//水平
                if (availableSize.Width < ThumbLength * 2)
                {
                    availableSize.Width = ThumbLength * 2;
                }
            }
            else
            {//垂直
                if (availableSize.Height < ThumbLength * 2)
                {
                    availableSize.Height = ThumbLength * 2;
                }
            }
            return availableSize;
            //var thumb = this.LowerThumb ?? this.HigherThumb;
            //if (thumb!=null)
            //{
            //    thumb.Measure(availableSize);
            //    return thumb.DesiredSize;
            //}
            //return base.MeasureOverride(availableSize);
        }

        protected override Size ArrangeOverride(Size arrangSize)
        {

            var thumbLength = this.ThumbLength;
            var fullLength = (this.Orientation == Orientation.Horizontal ? arrangSize.Width : arrangSize.Height);
            var totalLength = fullLength - 2 * thumbLength;//可滑动区域的总长度
            var spacing = (this.Orientation == Orientation.Horizontal ? arrangSize.Height : arrangSize.Width);

            double min = Minimum;
            double range = Math.Max(0.0, Maximum - min);

            double debtnStart = 0;//递减按钮起始位置
            CoerceLength(ref debtnStart, fullLength);
            double thumb1Start = Math.Min(range, LowerValue - min) / range * totalLength;//滑块1的起始位置
            CoerceLength(ref thumb1Start, fullLength);
            double thumb2Start = Math.Min(range, HigherValue - min) / range * totalLength + thumbLength;//滑块2的起始位置
            CoerceLength(ref thumb2Start, fullLength);
            double inbtnStart = thumb2Start + thumbLength;//递增按钮的起始位置
            CoerceLength(ref inbtnStart, fullLength);

            if (Orientation == Orientation.Horizontal)
            {
                if (this.DecreaseRepeatButton != null)
                {
                    this.DecreaseRepeatButton.Arrange(new Rect(new Point(debtnStart, 0), new Size(thumb1Start, spacing)));
                }
                if (this.LowerThumb != null)
                {
                    this.LowerThumb.Arrange(new Rect(new Point(thumb1Start, 0), new Size(thumbLength, spacing)));
                }
                if (this.HigherThumb != null)
                {
                    this.HigherThumb.Arrange(new Rect(new Point(thumb2Start, 0), new Size(thumbLength, spacing)));
                }
                if (this.IncreaseRepeatButton != null)
                {
                    this.IncreaseRepeatButton.Arrange(new Rect(new Point(inbtnStart, 0), new Size(totalLength + 2 * thumbLength - inbtnStart, spacing)));
                }
            }
            else
            {
                if (this.DecreaseRepeatButton != null)
                {
                    this.DecreaseRepeatButton.Arrange(new Rect(new Point(0, debtnStart), new Size(spacing, thumb1Start)));
                }
                if (this.LowerThumb != null)
                {
                    this.LowerThumb.Arrange(new Rect(new Point(0, thumb1Start), new Size(spacing, thumbLength)));
                }
                if (this.HigherThumb != null)
                {
                    this.HigherThumb.Arrange(new Rect(new Point(0, thumb2Start), new Size(spacing, thumbLength)));
                }
                if (this.IncreaseRepeatButton != null)
                {
                    this.IncreaseRepeatButton.Arrange(new Rect(new Point(0, inbtnStart), new Size(spacing, totalLength + 2 * thumbLength - inbtnStart)));
                }
            }

            return arrangSize;
        }
        /// <summary>
        /// 获取控件距离代表的值
        /// </summary>
        /// <param name="distance"></param>
        /// <returns></returns>
        public double ValueFromDistance(double distance)
        {
            var thumbLength = this.ThumbLength;
            var totalLength = (this.Orientation == Orientation.Horizontal ? this.DesiredSize.Width : this.DesiredSize.Height) - 2 * thumbLength;

            double range = Math.Max(0.0, Maximum - Minimum);

            return distance / totalLength * range;
        }



        protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnPropertyChanged(e);
            if (e.Property == LowerValueProperty || e.Property == HigherValueProperty)
            {

            }
            else if (e.Property == ThumbLengthProperty)
            {
                this.InvalidateMeasure();
            }
        }
        #endregion

    }
}
